/**
* 
**/
#include <stdio.h>
#include <stdlib.h>

/**
* 我总结的方法
首先从里层往外层数，0,0的原点算0层,每往外一层就加1
由此得出：
第几层: 0  1     2       3           4
个数和: 1 1+8 1+8+16 1+8+16+24 1+8+16+24+32
将个数和提取公因式得到第n层的和为：1 + 8(1+2+3+4...)
根据等差数列求和公式得到：1 + 8*( (1 + n)*n/2 ),最终得到如下公式
      f(n) = 4*(n+1)*n + 1  n>=0
由以上公式得到(1,-1)=9,(2,-2)=25,(3,-3)=49,(n,-n){n>0}的值，如下面数据所示
我们可以得到第n层起始的数值，然后根据这个点在本层哪一个边减去相应的数即可
得到层数用max = abs(x) > abs(y) ? abs(x) : abs(y)即可，x,y绝对值的最大值就是
这是大概思路，详细计算看代码
       -3,-3  -2,-3  -1,-3  0,-3  1,-3  2,-3  3,-3
-3,-3    43     44    45     46    47    48    49  3,-3
-3,-2    42     21    22     23    24    25    26  3,-2
-3,-1    41     20    7      8     9     10    27  3,-1
-3, 0    40     19    6      1     2     11    28  3,0
-3, 1    39     18    5      4     3     12    29  3,1
-3, 2    38     17    16     15    14    13    30  3,2
-3, 3    37     36    35     34    33    32    31  3,3
       -3, 3  -2,3   -1, 3  0, 3  1, 3  2, 3  3,3
另外还能看出右上角对角线为平方数也可推导:(n + n+1)^2,展开后得到一样公式
还有就是找规律最好先找平方、立方关系，然后再找总结的关系，可能会快一点
**/
int my(int x, int y)
{
  // tmp=1 表示原点为1,max取横纵坐标绝对值的最大值
  int max = abs(x) > abs(y) ? abs(x) : abs(y);
  int tmp = 4*max*(max+1) + 1;// 我推导出来的公式
  
  if (x != -y || x < 0) { /* 只去掉x+y=0直线的右上部分 */
    if (x == max) { // 右边
      tmp -= 7*max - y;
    } else if (x == -max) { // 左边
      tmp -= 3*max + y;
    }  else if (y == -max) { // 上边
      tmp -= max - x;
    } else { // 下边
      tmp -= 5*max + x;
    }
  }
  
  return tmp;
}

/**
* pdf给的答案
* 妈的比较不容易理解
**/
int foo(int x, int y)
{
  int t = abs(x) > abs(y) ? abs(x) : abs(y);
  int u = t+t;
  int v = u-1;
  v = v*v+u;
  if (x == -t) {
    v += u+t-y;
  } else if (y == -t) {
    v += 3*u+x-t;
  } else if (y == t) {
    v += t -x;
  } else {
    v += y - t;
  }
  return v;
}

/**
* 我想到的一种方案，螺旋遍历，最笨办法
 1   2   3   4   5   6
20  21  22  23  24   7
19  32  33  34  25   8
18  31  36  35  26   9
17  30  29  28  27  10
16  15  14  13  12  11
**/
void my1(int n)
{
  int i,j,k,m,a[100][100];
  i=j=m=0;
  k=1;
  n--;
  
  a[i][j] = k++;
  while (m < n/2) {
    for (j++;;j++) {
      a[i][j] = k++;
      if (j == n-m) {
        break;
      }
    }
    
    for (i++;;i++) {
      a[i][j] = k++;
      if (i == n-m) {
        break;
      }
    }
    
    for (j--;;j--) {
      a[i][j] = k++;
      if (j == m) {
        break;
      }
    }
    
    m++;
    
    for (i--;;i--) {
      a[i][j] = k++;
      if (i == m) {
        break;
      }
    }
  }
  
  if (n == 1) { // 妈逼的这个特殊啊,只剩3个
    a[i][j+1] = k++;
    a[i+1][j+1] = k++;
    a[i+1][j] = k++;
  } else if (n%2 == 1) { // 偶数最后有四个位置没填
    a[i][j+1] = k++;
    a[i][j+2] = k++;
    a[i+1][j+2] = k++;
    a[i+1][j+1] = k++;
  } else { // 奇数最后有一个位置没填
    a[i][j+1] = k;
  }
  
  for(i=0;i<=n;i++){
    for(j=0;j<=n;j++){
      printf("%4d",a[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}

/**
* pdf给的答案
* 也是螺旋遍历，但是比我的高明多了
* 膜拜ing
**/
void foo1(int n)
{
  int m=1,i,j,a[100][100];
  
  for (i=0;i<n;i++) {
    for (j=0;j<n;j++) {
      a[i][j] = 0; // 将所有值初始化
    }
  }
  
  for (i=0;i<n/2;i++) { // i (0~n/2),注意奇数和偶数
    for (j=0;j<n-i;j++) { // 本循环一直是上边
      if (a[i][j] == 0) {
        // printf("1,i:%d,j:%d,m:%d\n", i,j,m);
        a[i][j] = m++;
      }
    }
    
    for (j=i+1;j<n-i;j++) { // 本循环一直是右边
      if (a[j][n-1-i] == 0) {
        // printf("2,i:%d,j:%d,m:%d\n", j,n-1-i,m);
        a[j][n-1-i] = m++;
      }
    }
    
    for (j=n-1-i;j>i;j--) { // 本循环一直是下边
      if (a[n-1-i][j] == 0) {
        // printf("3,i:%d,j:%d,m:%d\n", n-1-i,j,m);
        a[n-1-i][j] = m++;
      }
    }
    
    for (j=n-1-i;j>i;j--) { // 本循环一直是左边
      if (a[j][i] == 0) {
        // printf("4,i:%d,j:%d,m:%d\n", j,i,m);
        a[j][i] = m++;
      }
    }
  }
  
  if (n%2 == 1) { // 为奇数则中间要填一个
    // printf("5,i:%d,j:%d,m:%d\n", n/2,n/2,m);
    a[n/2][n/2] = m;
  }
  
  for(i=0;i<n;i++){
    for(j=0;j<n;j++){
      printf("%4d",a[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}

int main(int argc, char *argv[])
{
  int x,y;
  for (y=-4;y<=4;y++) {
    for (x=-4;x<=4;x++) {
      printf("%4d", my(x,y));
    }
    printf("\n");
  }
  printf("\n");
  
  scanf("%d%d", &x,&y);
  printf("my(%d,%d) = %d\n", x,y,my(x,y));
  printf("foo(%d,%d) = %d\n", x,y,foo(x,y));
  
  //  下面是变种
  scanf("%d", &x);
  my1(x);
  
  foo1(x);
  
  return 0;
}
